#include "Common.h"
#include "PlayerController.h"
#include "PhysicsSystem.h"
#include "Scene.h"
#include <NxPhysics.h>
#include <NxControllerManager.h>
#include <NxCapsuleController.h>

PlayerController::PlayerController(Scene* scene, const Vector3& pos, float radius, float height)
	: mScene(scene)
	, mController(NULL)
	, mLocalOffset(0, -height * 0.5f, 0)
{
	NxControllerManager* controllerMgr = Physics::System::Instance().getControllerMgr();
	if (controllerMgr == NULL)
		return;

	NxCapsuleControllerDesc desc;
	desc.position.x		= pos.X;
	desc.position.y		= pos.Y + height * 0.5f;
	desc.position.z		= pos.Z;
	desc.height			= (float)Max(Math::Trunc(0.5f * height - radius) * 2, 5);
	desc.radius			= radius;
	desc.upDirection	= NX_Y;
	desc.slopeLimit		= 0.5f;
	desc.skinWidth		= 1.1f;
	desc.stepOffset		= 30.0;
	desc.callback		= NULL;	
	
	mController = controllerMgr->createController(scene->getPhysicsScene(), desc);
}

PlayerController::~PlayerController()
{
	if (mController)
	{
		NxControllerManager* controllerMgr = Physics::System::Instance().getControllerMgr();
		if (controllerMgr == NULL)
			return;

		controllerMgr->releaseController(*mController);
		mController = NULL;
	}
}

void PlayerController::Move(const Vector3& moveDir)
{
	NxVec3 trans(moveDir.X, moveDir.Y, moveDir.Z);
	NxU32 activeGroups = 0xffffffff;
	NxU32 collisionFlags = 0;
	mController->move(trans, activeGroups, 0.000001f, collisionFlags, 1.0f);
}

void PlayerController::SetPosition(const Vector3& pos)
{
	Vector3 controllerPos = pos - mLocalOffset;
	mController->setPosition(NxExtendedVec3(controllerPos.X, controllerPos.Y, controllerPos.Z));
}

Vector3 PlayerController::GetPosition()
{
	const NxExtendedVec3& contrllerPos = mController->getFilteredPosition();
	Vector3 ret((float)contrllerPos.x, (float)contrllerPos.y, (float)contrllerPos.z);
	return ret + mLocalOffset;
}
